package org.libarae.communication.common;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class User extends Common {
	//Defines user types
	public static enum Permission {
	    ADMINISTRATOR, MODERATOR, USER
	};
	
	private int mUID;
	private String mFirstName;
	private String mLastName;
	private String mUserName;
	private String mPassword;
	private Permission mStatus;
	
	//Address Stuffs :)
	private String mAddress;
	private String mCity;
	private String mState;
	private String mZipCode;
	
	public User(){
		super();
	}
	
	public User(int UID, String firstName, String lastName, String userName, String password, Permission status, String address, String city, String state, String zip) {
		this.mUID = UID;
		this.mFirstName = firstName;
		this.mLastName = lastName;
		this.mUserName = userName.toLowerCase();;
		this.mPassword = getMd5(password);
		this.mStatus = status;
		this.mAddress = address;
		this.mCity = city;
		this.mState = state;
		this.mZipCode = zip;
	}
	
	public void setUser(int UID, String firstName, String lastName, String userName, String password, Permission status, String address, String city, String state, String zip) {
		this.mUID = UID;
		this.mFirstName = firstName;
		this.mLastName = lastName;
		this.mUserName = userName.toLowerCase();;
		this.mPassword = getMd5(password);
		this.mStatus = status;
		this.mAddress = address;
		this.mCity = city;
		this.mState = state;
		this.mZipCode = zip;
	}
	
	@Override
	public void decodeXML(Node root) {
		NodeList nodeList = root.getChildNodes();

		// set all of the nodes in their proper places
		for (int i = 0; i < nodeList.getLength(); i++) {			
			// find what node we have
			String nodeName = nodeList.item(i).getNodeName();
			if (nodeName.equals("mFirstName")) {
				mFirstName = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mUID")) {
				mUID = Integer.parseInt(nodeList.item(i).getTextContent());
			}
			else if (nodeName.equals("mLastName")) {
				mLastName = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mUserName")) {
				mUserName = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mPassword")) {
				mPassword = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mAddress")) {
				mAddress = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mCity")) {
				mCity = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mState")) {
				mState = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mZipCode")) {
				mZipCode = nodeList.item(i).getTextContent();
			}		
			else if (nodeName.equals("mStatus")) {
				switch(Integer.parseInt(nodeList.item(i).getTextContent())){
					case 0:
						mStatus = Permission.ADMINISTRATOR;
					break;
					case 1:
						mStatus = Permission.MODERATOR;
					break;
					case 2:
						mStatus = Permission.USER;
					break;
				}
			}		
			else {
				System.err.println("Unknow field in object XML: " + nodeName);
			}
		}		
	}
	
	
	@Override
	public void createXml(Document doc, Element root) {	
		Element node = doc.createElement("mUID");
		node.setTextContent(mUID+"");
		root.appendChild(node);
		
		node = doc.createElement("mFirstName");
		node.setTextContent(mFirstName);
		root.appendChild(node);
		
		node = doc.createElement("mLastName");
		node.setTextContent(mLastName);
		root.appendChild(node);
		
		node = doc.createElement("mUserName");
		node.setTextContent(mUserName);
		root.appendChild(node);
		
		node = doc.createElement("mPassword");
		node.setTextContent(mPassword);
		root.appendChild(node);
		
		node = doc.createElement("mAddress");
		node.setTextContent(mAddress);
		root.appendChild(node);
		
		node = doc.createElement("mCity");
		node.setTextContent(mCity);
		root.appendChild(node);
		
		node = doc.createElement("mState");
		node.setTextContent(mState);
		root.appendChild(node);
		
		node = doc.createElement("mZipCode");
		node.setTextContent(mZipCode);
		root.appendChild(node);
		
		//if the status is not null
		if(mStatus != null){
			node = doc.createElement("mStatus");
			node.setTextContent(mStatus.ordinal()+"");
			root.appendChild(node);	
		}
	}
	
	public int getUID() {
		return mUID;
	}
	public void setUID(int mUID) {
		this.mUID = mUID;
	}
	public String getFirstName() {
		return mFirstName;
	}
	public void setFirstName(String mFirstName) {
		this.mFirstName = mFirstName;
	}
	public String getLastName() {
		return mLastName;
	}
	public void setLastName(String mFirstLast) {
		this.mLastName = mFirstLast;
	}
	public String getUserName() {
		return mUserName.toLowerCase();
	}
	public void setUserName(String mUserName) {
		this.mUserName = mUserName;
	}
	public String getPassword() {
		return mPassword;
	}
	public void setPassword(String mPassword) {
		this.mPassword =  getMd5(mPassword);
	}
	public Permission getStatus() {
		return mStatus;
	}
	public void setStatus(Permission mStatus) {
		this.mStatus = mStatus;
	}
	public String getAddress() {
		return mAddress;
	}
	public void setAddress(String mAddress) {
		this.mAddress = mAddress;
	}
	public String getCity() {
		return mCity;
	}
	public void setCity(String mCity) {
		this.mCity = mCity;
	}
	public String getState() {
		return mState;
	}
	public void setState(String mState) {
		this.mState = mState;
	}
	public String getZipCode() {
		return mZipCode;
	}
	public void setZipCode(String mZipCode) {
		this.mZipCode = mZipCode;
	}
	
	//Used to has the password when it is set.
	public static String getMd5(String pInput){
		try {
			//try to get the digester
 			MessageDigest lDigest = MessageDigest.getInstance("MD5");
			lDigest.update(pInput.getBytes());
			BigInteger lHashInt = new BigInteger(1, lDigest.digest());
			//return the formated string
			return String.format("%1$032X", lHashInt);
		} catch(NoSuchAlgorithmException lException) {
			System.err.println("Error hashing user password");
			return null;
		}
	}	
}
